﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RaisingStudio.Data.Expressions
{
    /// <summary>
    /// Operation expression
    /// </summary>
    [Serializable]
    public class OperationExpression : ExpressionElement
    {
        private OperationElement _Element;
        /// <summary>
        /// element.
        /// </summary>
        public OperationElement Element
        {
            get
            {
                return this._Element;
            }
            set
            {
                this._Element = value;
            }
        }

        private ElementOperator _Operator;
        /// <summary>
        /// Operation.
        /// </summary>
        public ElementOperator Operator
        {
            get
            {
                return this._Operator;
            }
            set
            {
                this._Operator = value;
            }
        }

        private object _Value;
        /// <summary>
        /// value.
        /// </summary>
        public object Value
        {
            get
            {
                return this._Value;
            }
            set
            {
                this._Value = value;
            }
        }

        #region Constructor
        public OperationExpression()
        {
        }

        public OperationExpression(string columnName, ElementOperator expressionOperator, object value)
        {
            this._Element = new ColumnExpression(columnName);
            this._Operator = expressionOperator;
            this._Value = value;
        }

        public OperationExpression(OperationElement operationElement, ElementOperator expressionOperator, object value)
        {
            this._Element = operationElement;
            this._Operator = expressionOperator;
            this._Value = value;
        }
        #endregion


        #region 符重载
        public static RelationExpression operator &(OperationExpression operationExpression1, OperationExpression operationExpression2)
        {
            return new RelationExpression(operationExpression1, RelationOperator.And, operationExpression2);
        }

        public static RelationExpression operator &(OperationExpression operationExpression, RelationExpression relationExpression)
        {
            return new RelationExpression(operationExpression, RelationOperator.And, relationExpression);
        }

        public static RelationExpression operator |(OperationExpression operationExpression1, OperationExpression operationExpression2)
        {
            return new RelationExpression(operationExpression1, RelationOperator.Or, operationExpression2);
        }

        public static RelationExpression operator |(OperationExpression operationExpression, RelationExpression relationExpression)
        {
            return new RelationExpression(operationExpression, RelationOperator.Or, relationExpression);
        }

        public static RelationExpression operator !(OperationExpression operationExpression)
        {
            return new RelationExpression(RelationOperator.Not, operationExpression);
        }


        public static OperationExpression operator ~(OperationExpression operationExpression)
        {
            switch (operationExpression.Operator)
            {
                case ElementOperator.Equal:
                    {
                        operationExpression.Operator = ElementOperator.NotEqual;
                        break;
                    }
                case ElementOperator.NotEqual:
                    {
                        operationExpression.Operator = ElementOperator.Equal;
                        break;
                    }
                case ElementOperator.Greater:
                    {
                        operationExpression.Operator = ElementOperator.LessOrEqual;
                        break;
                    }
                case ElementOperator.LessOrEqual:
                    {
                        operationExpression.Operator = ElementOperator.Greater;
                        break;
                    }
                case ElementOperator.Less:
                    {
                        operationExpression.Operator = ElementOperator.GreaterOrEqual;
                        break;
                    }
                case ElementOperator.GreaterOrEqual:
                    {
                        operationExpression.Operator = ElementOperator.Less;
                        break;
                    }
                case ElementOperator.IsNull:
                    {
                        operationExpression.Operator = ElementOperator.IsNotNull;
                        break;
                    }
                case ElementOperator.IsNotNull:
                    {
                        operationExpression.Operator = ElementOperator.IsNull;
                        break;
                    }
                case ElementOperator.Like:
                    {
                        operationExpression.Operator = ElementOperator.NotLike;
                        break;
                    }
                case ElementOperator.NotLike:
                    {
                        operationExpression.Operator = ElementOperator.Like;
                        break;
                    }
                case ElementOperator.Between:
                    {
                        operationExpression.Operator = ElementOperator.NotBetween;
                        break;
                    }
                case ElementOperator.NotBetween:
                    {
                        operationExpression.Operator = ElementOperator.Between;
                        break;
                    }
                case ElementOperator.In:
                    {
                        operationExpression.Operator = ElementOperator.NotIn;
                        break;
                    }
                case ElementOperator.NotIn:
                    {
                        operationExpression.Operator = ElementOperator.In;
                        break;
                    }
            }
            return operationExpression;
        }
        #endregion
        #region 符重载
        public static ConditionExpression operator ^(OperationExpression operationExpression, SortingExpression sortingExpression)
        {
            return (new ConditionExpression(operationExpression)).OrderBy(sortingExpression);
        }

        public static ConditionExpression operator ^(OperationExpression operationExpression, ColumnExpression columnExpression)
        {
            return (new ConditionExpression(operationExpression)).OrderBy(columnExpression);
        }

        public static ConditionExpression operator ^(OperationExpression operationExpression, string columnName)
        {
            return (new ConditionExpression(operationExpression)).OrderBy(columnName);
        }
        #endregion
    }
}
